package com.je.meta.service.project;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.service.MetaRbacService;
import com.je.common.base.service.MetaService;
import com.je.common.base.spring.SpringContextHolder;
import com.je.common.base.util.ProjectContextHolder;
import com.je.common.base.util.TreeUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.model.dd.DicInfoVo;
import com.je.meta.rpc.project.ProjectOrgRpcService;
import com.je.meta.rpc.project.ProjectUserRpcService;
import com.je.servicecomb.RpcSchemaFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("projectWorkflowOrgUserTreeService")
public class ProjectWorklfowOrgUserTreeService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private MetaRbacService metaRbacService;

    public JSONTreeNode buildTree(DicInfoVo dicInfoVo) {

        boolean multiple = false;
        if (dicInfoVo.getCustomerVariables().get("multiple") != null && dicInfoVo.getCustomerVariables().get("multiple") instanceof Boolean) {
            multiple = (boolean) dicInfoVo.getCustomerVariables().get("multiple");
        }
        String wfSql = "";
        if (dicInfoVo.getCustomerVariables().get("wfSql") != null) {
            wfSql = String.valueOf(dicInfoVo.getCustomerVariables().get("wfSql"));
        }

        JSONTreeNode root = TreeUtil.buildRootNode();
        if (ProjectContextHolder.getProject() == null) {
            return root;
        }

        DynaBean orgMappingBean = metaService.selectOne("JE_RBAC_PROJECTORGMAPPING",
                ConditionsWrapper.builder().eq("PROJECTORGMAPPING_ENABLE_CODE", "1"));
        if (orgMappingBean == null) {
            return root;
        }

        String orgProductCode = orgMappingBean.getStr("PROJECTORGMAPPING_PRODUCT_CODE");
        String orgTableCode = orgMappingBean.getStr("PROJECTORGMAPPING_TABLE_CODE");
        String orgPkFieldCode = orgMappingBean.getStr("PROJECTORGMAPPING_PKFIELD_CODE");
        String orgNameFieldCode = orgMappingBean.getStr("PROJECTORGMAPPING_NAMEFIELD_CODE");
        String orgCodeFieldCode = orgMappingBean.getStr("PROJECTORGMAPPING_CODEFIELD_CODE");
        String orgParentIdFieldCode = orgMappingBean.getStr("PROJECTORGMAPPING_PARENTFIELD_CODE");
        String orgOrderFieldCode = orgMappingBean.getStr("PROJECTORGMAPPING_ORDERFIELD_CODE");
        String orgProjectIdFieldCode = orgMappingBean.getStr("PROJECTORGMAPPING_PROJECTPKFIELD_CODE");
        String orgGlSql = orgMappingBean.getStr("PROJECTORGMAPPING_GLSQL");
        ProjectOrgRpcService projectOrgRpcService;
        if ("meta".equals(orgProductCode)) {
            projectOrgRpcService = SpringContextHolder.getBean(ProjectOrgRpcService.class);
        } else {
            projectOrgRpcService = RpcSchemaFactory.getRemoteProvierClazz(orgProductCode, "projectOrgRpcService", ProjectOrgRpcService.class);
        }

        List<DynaBean> deptBeanList = projectOrgRpcService.findProjectOrgWithOrder(orgTableCode, orgProjectIdFieldCode,
                ProjectContextHolder.getProject().getId(), orgOrderFieldCode, orgGlSql);
        if (deptBeanList == null || deptBeanList.isEmpty()) {
            return root;
        }

        DynaBean userMappingBean = metaService.selectOne("JE_RBAC_PROJECTUSERMAPPING",
                ConditionsWrapper.builder().eq("PROJECTUSERMAPPING_ENABLE_CODE", "1"));
        if (userMappingBean == null) {
            return root;
        }

        String userProductCode = userMappingBean.getStr("PROJECTUSERMAPPING_PRODUCT_CODE");
        String userTableCode = userMappingBean.getStr("PROJECTUSERMAPPING_TABLE_CODE");
        String userProjectIdFieldCode = userMappingBean.getStr("PROJECTUSERMAPPING_PROJECTPKFIELD_CODE");
        String userDeptAccountUserIdFieldCode = userMappingBean.getStr("PROJECTUSERMAPPING_SYSUSERPKFIELD_CODE");
        String userOrgIdFieldCode = userMappingBean.getStr("PROJECTUSERMAPPING_DEPTIDFIELD_CODE");
        String userTableGlSql = userMappingBean.getStr("PROJECTUSERMAPPING_GLSQL");

        ProjectUserRpcService projectUserRpcService;
        if ("meta".equals(userProductCode)) {
            projectUserRpcService = SpringContextHolder.getBean(ProjectUserRpcService.class);
        } else {
            projectUserRpcService = RpcSchemaFactory.getRemoteProvierClazz(userProductCode, "projectUserRpcService", ProjectUserRpcService.class);
        }

        if (!Strings.isNullOrEmpty(userTableGlSql)) {
            userTableGlSql += " " + wfSql;
        } else {
            userTableGlSql = wfSql;
        }

        List<DynaBean> userBeanList = projectUserRpcService.findProjectUserWithOrder(userTableCode, userProjectIdFieldCode,
                ProjectContextHolder.getProject().getId(), "SY_CREATETIME", userTableGlSql);
        List<String> accDeptIds = new ArrayList<>();
        for (DynaBean dynaBean : userBeanList) {
            accDeptIds.add(dynaBean.getStr(userDeptAccountUserIdFieldCode));
        }

        List<DynaBean> accountDeptBeanList = metaRbacService.selectByTableCodeAndNativeQuery("JE_RBAC_VACCOUNTDEPT",
                NativeQuery.build().in("JE_RBAC_ACCOUNTDEPT_ID", accDeptIds));
        Map<String, DynaBean> accountDeptBeanMap = new HashMap<>();
        for (DynaBean dynaBean : accountDeptBeanList) {
            accountDeptBeanMap.put(dynaBean.getStr("JE_RBAC_ACCOUNTDEPT_ID"), dynaBean);
        }

        JSONTreeNode eachNode;
        String rootId = "";
        for (DynaBean dynaBean : deptBeanList) {
            if ("ROOT".equalsIgnoreCase(dynaBean.getStr("SY_NODETYPE"))) {
                rootId = dynaBean.getStr(orgPkFieldCode);
            }
        }

        for (DynaBean dynaBean : deptBeanList) {
            if (!rootId.equals(dynaBean.getStr(orgParentIdFieldCode))) {
                continue;
            }
            eachNode = buildDeptNode(root, dynaBean, userBeanList, orgPkFieldCode, orgNameFieldCode, orgCodeFieldCode,
                    userDeptAccountUserIdFieldCode, userOrgIdFieldCode, accountDeptBeanMap, multiple);
            recursiveBuildDeptTree(eachNode, deptBeanList, userBeanList,
                    orgPkFieldCode, orgNameFieldCode, orgCodeFieldCode, orgParentIdFieldCode,
                    userDeptAccountUserIdFieldCode, userOrgIdFieldCode, accountDeptBeanMap, multiple);
            root.getChildren().add(eachNode);
        }

        return root;
    }

    private void recursiveBuildDeptTree(JSONTreeNode parentNode, List<DynaBean> deptBeanList,
                                        List<DynaBean> userBeanList, String orgPkFieldCode,
                                        String orgNameFieldCode, String orgCodeFieldCode, String orgParentIdFieldCode,
                                        String userPkFieldCode, String userOrgIdFieldCode,
                                        Map<String, DynaBean> accountDeptBeanMap, boolean multiple) {
        JSONTreeNode childNode;
        for (DynaBean dynaBean : deptBeanList) {
            if (!parentNode.getId().equals(dynaBean.getStr(orgParentIdFieldCode))) {
                continue;
            }
            childNode = buildDeptNode(parentNode, dynaBean, userBeanList,
                    orgPkFieldCode, orgNameFieldCode, orgCodeFieldCode, userPkFieldCode,
                    userOrgIdFieldCode, accountDeptBeanMap, multiple);
            recursiveBuildDeptTree(childNode, deptBeanList, userBeanList,
                    orgPkFieldCode, orgNameFieldCode, orgCodeFieldCode, orgParentIdFieldCode,
                    userPkFieldCode, userOrgIdFieldCode, accountDeptBeanMap, multiple);
            parentNode.getChildren().add(childNode);
        }
    }

    private JSONTreeNode buildDeptNode(JSONTreeNode parentNode, DynaBean deptBean,
                                       List<DynaBean> userBeanList, String orgPkFieldCode,
                                       String orgNameFieldCode, String orgCodeFieldCode,
                                       String userPkFieldCode, String userOrgIdFieldCode, Map<String, DynaBean> accountDeptBeanMap, boolean multiple) {
        JSONTreeNode deptNode = TreeUtil.buildTreeNode(deptBean.getStr(orgPkFieldCode),
                deptBean.getStr(orgNameFieldCode),
                deptBean.getStr(orgCodeFieldCode),
                "",
                "dept",
                "",
                parentNode.getId());
        deptNode.setBean(deptBean.getValues());
        for (DynaBean userBean : userBeanList) {
            if (userBean.getStr(userOrgIdFieldCode).equals(deptBean.getStr(orgPkFieldCode))) {
                DynaBean user = accountDeptBeanMap.get(userBean.getStr(userPkFieldCode));
                parseAccountDepartmentToTree(deptNode, user, multiple);
            }
        }

        return deptNode;
    }


    public static void parseAccountDepartmentToTree(JSONTreeNode resultJSONTreeNode, DynaBean user, Boolean multiple) {
        JSONTreeNode node = new JSONTreeNode();
        node.setId(user.getStr("JE_RBAC_ACCOUNTDEPT_ID"));
        node.setCode(user.getStr("ACCOUNT_CODE"));
        node.setText(user.getStr("ACCOUNT_NAME"));
        node.setNodeType("LEAF");
        JSONObject nodeInfo = new JSONObject();
        nodeInfo.put("sex", user.getStr("ACCOUNT_SEX"));
        nodeInfo.put("ACCOUNT_NAME", user.getStr("ACCOUNT_NAME"));
        node.setNodeInfo(nodeInfo.toJSONString());
        node.setNodeInfoType("json");
        node.setIcon("fal fa-user");
        node.setParent(resultJSONTreeNode.getId());
        node.setChecked(multiple);
        node.setLayer(resultJSONTreeNode.getLayer() + 1);
        node.setBean(user.getValues());
        resultJSONTreeNode.getChildren().add(node);
    }


}
